package com.better.common.mongo.repository;


import com.better.common.mongo.model.BaseModel;
import com.better.common.mongo.model.SpringDataPageable;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.NoRepositoryBean;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * 业务DAO就可以继承CommonRepository
 * Created by Administrator on 2017/11/1.
 */
//避免spring扫描CommonRepository
//接口只是扩展了Repository，那么只需实现自定义的业务方法
//接口扩展了MongoRepository，就要实现所有相关的基础方法
@NoRepositoryBean
@Configuration
@EnableAutoConfiguration
@ComponentScan
public interface CommonRepository<T extends BaseModel, ID extends Serializable> extends MongoRepository<T, ID> {
    /**
     * 自定义查询query 分页
     *
     * @param query 查询dsl语句
     * @param p     分页对象，传入空，代表查询所有
     * @author:
     * @date :2017/11/17
     */
    public Page<T> findPageByQuery(Query query, Pageable p);

    /**
     * 自定义查询query 分页
     *
     * @param query 查询dsl语句
     * @author:
     * @date :2017/11/17
     */
    public List<T> findListByQuery(Query query);

    /**
     * 自定义  Criteria 分页查询
     *
     * @param criteria 标准查询语句
     * @param p        分页对象，传入空，代表查询所有
     * @author:
     * @date :2017/11/17
     */
    public Page<T> findPageByCriteria(Criteria criteria, Pageable p);

   /**
    * 自定义 Criteria 查询
   *@author:
   *@date :2018/1/8
   */
    public List<T> findByCriteria(Criteria criteria);

   /**
    * 自定义 Criteria 查询
    *@author:
    *@date :2018/1/8
    */
   public List<T> findForField(DBObject dbObject, BasicDBObject basicDBObject);



    /**
     * 批量保存更新（如果不存在就查询，存在就更新）
     *
     * @author:
     * @date :2017/11/17
     */
    public void batchSave(List<T> obj);

    /**
     * 根据主键IDs 批量删除
     *
     * @author:
     * @date :2017/11/17
     */
    public void batchDelete(List<ID> pks);

    /**
     * 更新文档
     *
     * @param id             更新主键
     * @param updateFieldMap key:需要更新的属性  value:对应的属性值
     * @author:
     * @date :2017/11/17
     */
    public void update(ID id, Map<String, Object> updateFieldMap);

    /**
     * 更新文档
     *
     * @param queryParamMap  key:查询属性  value:对应的属性值
     * @param updateFieldMap key:需要更新的属性  value:对应的属性值
     * @author:
     * @date :2017/11/17
     */
    public void update(Map<String, Object> queryParamMap, Map<String, Object> updateFieldMap);

    /**
     * 分页查询列表
     *
     * @param pageIndex 当前页
     * @param pageSize  当前页面条数
     * @param sortMap   排序 key:排序字段 value:升序0或降序1
     * @return
     */
    public Page<T> findPage(Integer pageIndex, Integer pageSize, Map<String, Integer> sortMap);

    /**
     * 多条件查询排序
     *
     * @param paramMap        查询 key:查询字段 value:匹配值（数字和_id精确查询，字符串默认模糊查询）
     * @param sortMap         排序 key:排序字段 value:升序0或降序1
     * @param includeParamMap 映射字段,为空，类似 select * from dual  不为空，类似 select filed1 ,filed2 ,...from dual
     * @author:
     * @date :2017/11/17
     */
    public List<T> findListBy(Map<String, Object> paramMap, Map<String, Integer> sortMap, Map<String, Object> includeParamMap);

    /**
     * 多条件查询排序
     *
     * @param paramMap 查询 key:查询字段 value:匹配值（数字和_id精确查询，字符串默认模糊查询）
     * @param sortMap  排序 key:排序字段 value:升序0或降序1
     * @author:
     * @date :2017/11/17
     */
    public List<T> findListBy(Map<String, Object> paramMap, Map<String, Integer> sortMap);

    /**
     * 多条件查询
     *
     * @param paramMap 查询 key:查询字段 value:匹配值（数字和_id精确查询，字符串默认模糊查询）
     * @author:
     * @date :2017/11/17
     */
    public List<T> findListBy(Map<String, Object> paramMap);

    /**
     * 多条件查询
     *
     * @param propertyName 查询字段
     * @param value        匹配值
     * @author:
     * @date :2017/11/17
     */
    public List<T> findListBy(String propertyName, Object value);

    /**
     * 按条件获取对象
     *
     * @param propertyName 查询字段
     * @param value        匹配值
     * @author:
     * @date :2017/11/17
     */
    public T findUniqueBy(String propertyName, Object value);

    /**
     * 按条件获取对象
     *
     * @param paramMap 查询 key:查询字段 value:匹配值（数字和_id精确查询，字符串默认模糊查询）
     * @author:
     * @date :2017/11/17
     */
    public T findUniqueBy(Map<String, Object> paramMap);

    /**
     * 多条件查询排序分页
     *
     * @param paramMap  查询 key:查询字段 value:匹配值（数字和_id精确查询，字符串默认模糊查询）
     * @param sortMap   排序 key:排序字段 value:升序0或降序1
     * @param pageIndex 当前页
     * @param pageSize  当前页面条数
     * @author:
     * @date :2017/11/17
     */
    public Page<T> findPageBy(Map<String, Object> paramMap, Map<String, Integer> sortMap, Integer pageIndex, Integer pageSize);


    /**
     * 多条件查询分页
     *
     * @param paramMap  查询 key:查询字段 value:匹配值（数字和_id精确查询，字符串默认模糊查询）
     * @param pageIndex 当前页
     * @param pageSize  当前页面条数
     * @author:
     * @date :2017/11/17
     */
    public Page<T> findPageBy(Map<String, Object> paramMap, Integer pageIndex, Integer pageSize);

    /**
     * 条件查询分页
     *
     * @param propertyName 查询字段
     * @param pageIndex    当前页
     * @param pageSize     当前页面条数
     * @author:
     * @date :2017/11/17
     */
    public Page<T> findPageBy(String propertyName, Object value, Integer pageIndex, Integer pageSize);

    /**
     * 按照查询添加统计记录
     *
     * @param paramMap 查询 key:查询字段 value:匹配值（数字和_id精确查询，字符串默认模糊查询）
     * @author:
     * @date :2017/11/20
     */
    long countBy(Map<String, Object> paramMap);

    /**
     * 分页查询内嵌文档
     *
     * @param aggregation 聚合条件
     * @param inputType   对应查询数据库的实体对象
     * @param outputType  对应需要输出的实体对象
     * @author:
     * @date :2017/12/1
     */
    <O> List<O> findNestPage(TypedAggregation<?> aggregation, Class<?> inputType, Class<O> outputType);

    /**
     * 查询内嵌文档总数
     *
     * @param aggregation 聚合条件
     * @param outputType  对应需要输出的实体对象
     * @param select  分组字段是否匹配查询条件
     * @author:
     * @date :2017/12/1
     */
/*    <O> AggregationResults<O> findNestCout(TypedAggregation<?> aggregation, Class<O> outputType);*/

    long findNestCout(TypedAggregation<?> aggregation, Class outputType,boolean select);

    /**
     * 分页查询内嵌文档
     *
     * @param querParms      聚合条件 ,内嵌文档直接使用 英文点号分割
     * @param filedAlias     字段映射关系，如果字段为内嵌文档字段，无需使用英文点号分开
     *                       如果value 为空，则代表展示的字段，类似sql select filed1 ,filed2,... from dual
     *                       如果value 不为空 则代表字段需要映射别名  类似sql select fild1 as a ,fild2 as b ...from dual
     * @param sortMap        排序 key:排序字段 value:升序0或降序1 （如何使内嵌文档字段 内嵌属性.内嵌文档字段）
     * @param nestProperties 内嵌文档属性
     * @param groupFiled     子文档分组字段 ，内嵌属性.内嵌文档字段
     * @param pageable       分页对象，如果为空查询所有
     * @param inputType      对应查询数据库的实体对象类
     * @param outputType     对应需要输出的实体对象类
     * @author:
     * @date :2017/12/1
     */
    <O> Page<O> findNestPage(Map<String, Object> querParms, Map<String, String> filedAlias, Map<String, Integer> sortMap, String nestProperties, String groupFiled, SpringDataPageable pageable, Class<?> inputType, Class<O> outputType);

    /**
     * 分页查询内嵌文档
     *
     * @param querParms      聚合条件 ,内嵌文档直接使用 英文点号分割
     * @param filedAlias     字段映射关系，如果字段为内嵌文档字段，无需使用英文点号分开
     *                       如果value 为空，则代表展示的字段，类似sql select filed1 ,filed2,... from dual
     *                       如果value 不为空 则代表字段需要映射别名  类似sql select fild1 as a ,fild2 as b ...from dual
     * @param nestProperties 内嵌文档属性
     * @param groupFiled     子文档分组字段 ，内嵌属性.内嵌文档字段
     * @param pageable       分页对象，如果为空查询所有
     * @param inputType      对应查询数据库的实体对象类
     * @param outputType     对应需要输出的实体对象类
     * @author:
     * @date :2017/12/1
     */
    <O> Page<O> findNestPage(Map<String, Object> querParms, Map<String, String> filedAlias, String nestProperties, String groupFiled, SpringDataPageable pageable, Class<?> inputType, Class<O> outputType);


    /**
     * 分页查询内嵌文档
     *
     * @param criteria      聚合条件 ,支撑多种查询条件
     * @param filedAlias     字段映射关系，如果字段为内嵌文档字段，无需使用英文点号分开
     *                       如果value 为空，则代表展示的字段，类似sql select filed1 ,filed2,... from dual
     *                       如果value 不为空 则代表字段需要映射别名  类似sql select fild1 as a ,fild2 as b ...from dual
     * @param nestProperties 内嵌文档属性
     * @param groupFiled     子文档分组字段 ，内嵌属性.内嵌文档字段
     * @param pageable       分页对象，如果为空查询所有
     * @param inputType      对应查询数据库的实体对象类
     * @param outputType     对应需要输出的实体对象类
     * @author:
     * @date :2017/12/1
     */
    <O> Page<O> findNestPage(NestCriteria criteria, Map<String, String> filedAlias, String nestProperties, String groupFiled, SpringDataPageable pageable, Class<?> inputType, Class<O> outputType);

    /**
     * 分页查询内嵌文档
     *
     * @param criteria      聚合条件 ,支撑多种查询条件
     * @param filedAlias     字段映射关系，如果字段为内嵌文档字段，无需使用英文点号分开
     *                       如果value 为空，则代表展示的字段，类似sql select filed1 ,filed2,... from dual
     *                       如果value 不为空 则代表字段需要映射别名  类似sql select fild1 as a ,fild2 as b ...from dual
     * @param sortMap        排序 key:排序字段 value:升序0或降序1 （如何使内嵌文档字段 内嵌属性.内嵌文档字段）
     * @param nestProperties 内嵌文档属性
     * @param groupFiled     子文档分组字段 ，内嵌属性.内嵌文档字段
     * @param pageable       分页对象，如果为空查询所有
     * @param inputType      对应查询数据库的实体对象类
     * @param outputType     对应需要输出的实体对象类
     * @author:
     * @date :2017/12/1
     */
    <O> Page<O> findNestPage(NestCriteria criteria, Map<String, String> filedAlias, Map<String, Integer> sortMap, String nestProperties, String groupFiled, SpringDataPageable pageable, Class<?> inputType, Class<O> outputType);
}
